package com.itcam.interview.pro00.thread;


import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : Cammy.Wu
 * Description : 
 */

public class ShutDownThreadPool {
    public static ThreadPoolExecutor pool = new ThreadPoolExecutor(
            10,
            15,
            0L,
            TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<>(10)
    );

    /**
     * 该方法用于模拟线程执行任务时的休眠操作
     * @param index 当前线程的索引，用于标识不同的线程
     */
    private static void sleepMethod(int index) {
        try {
            // 生成一个 0 到 10000 毫秒之间的随机休眠时间
            long sleepTime = new Double(Math.random() * 10000).longValue();
            // 使当前线程休眠指定的时间
            Thread.sleep(sleepTime);
            // 输出当前线程执行结束的信息
            System.out.println("当前线程执行结束：" + index);
        } catch (InterruptedException e) {
            // 当线程在休眠过程中被中断时，打印异常堆栈信息
            e.printStackTrace();
        }
    }


    private static int taskCount = 0;

    public static void main(String[] args) throws InterruptedException {
//        extracted();
//        extracted1();
//        extracted2();
//        extracted3();
        Future future = pool.submit(() -> sleepMethod(1));
        while (!future.isDone()) {
            Thread.sleep(1000);
            System.out.println("还没停止...");
        }
        System.out.println("全部执行完成");
    }


    private static void extracted3() throws InterruptedException {
        /**
         * 创建一个可重入锁实例，用于保证对共享变量 taskCount 的线程安全操作
         */
        Lock lock = new ReentrantLock();
        // 循环 10 次，向线程池提交 10 个任务
        for (int i = 0; i < 10; i++) {
            // 由于 Lambda 表达式只能引用 final 或 effectively final 的局部变量，因此需要将 i 的值赋给一个新的变量 index
            int index = i;
            // 向线程池提交一个任务
            pool.execute(() -> {
                // 调用 sleepMethod 方法，模拟任务执行
                sleepMethod(index);
                // 获取锁，确保在同一时间只有一个线程可以执行下面的代码块
                lock.lock();
                // 任务完成后，将已完成任务的计数器加 1
                taskCount++;
                // 释放锁，允许其他线程获取锁并执行代码块
                lock.unlock();
            });
        }

        while (taskCount < 10) {
            Thread.sleep(1000);
            System.out.println("还没停止...当前完成任务树：" + taskCount);
        }
        System.out.println("全部执行完成");
    }

    private static void extracted2() throws InterruptedException {
        /**
         * 创建一个 CountDownLatch 实例，初始计数为 10，用于等待 10 个任务完成
         */
        CountDownLatch latch = new CountDownLatch(10);
        // 循环 10 次，向线程池提交 10 个任务
        for (int i = 0; i < 10; i++) {
            // 由于 Lambda 表达式只能引用 final 或 effectively final 的局部变量，因此需要将 i 的值赋给一个新的变量 index
            int index = i;
            // 向线程池提交一个任务
            pool.execute(() -> {
                // 调用 sleepMethod 方法，模拟任务执行
                sleepMethod(index);
                // 任务完成后，将计数器减 1
                latch.countDown();
                // 输出当前计数器的数量
                System.out.println("当前计数器数量：" + latch.getCount());
            });
        }
        // 当前线程阻塞，等待计数器置为 0，即所有任务都完成
        latch.await();
        // 所有任务完成后，输出提示信息
        System.out.println("全部执行完成");
    }

    private static void extracted1() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            int index = i;
            pool.execute(() -> sleepMethod(index));
        }
        while (!(pool.getTaskCount() == pool.getCompletedTaskCount())) {
            System.out.println("任务总数：" + pool.getTaskCount() + ":已经完成任务数：" + pool.getCompletedTaskCount());
            Thread.sleep(1000);
            System.out.println("还没停止");
        }
        System.out.println("全部执行完毕");
    }

    private static void extracted() throws InterruptedException {
    /*
        shutdown:对线程进行有序关闭
        isTerminated:判断线程池中的所有任务是否在关闭后完成
     */
        for (int i = 0; i < 10; i++) {
            int index = i;
            pool.execute(() -> sleepMethod(index));
        }
        pool.shutdown();
        while (!pool.isTerminated()) {
            Thread.sleep(1000);
            System.out.println("还没停止");
        }
        System.out.println("全部执行完毕");
    }
}
